package com.ltmonitor.jt808.service.impl;

import com.ltmonitor.app.GpsConnection;
import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.jt808.protocol.T808Message;
import com.ltmonitor.jt808.service.IGpsConnectionService;
import com.ltmonitor.jt808.service.IOnlineAnalyzeService;
import com.ltmonitor.service.IOnlineRecordService;
import com.ltmonitor.service.IRealDataService;
import com.ltmonitor.util.DateUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Service("gpsConnectionService")
public class GpsConnectionService implements IGpsConnectionService {
    private Logger logger = Logger.getLogger(GpsConnectionService.class);
    boolean startUpdate = false;

    private  ConcurrentMap<String, GpsConnection> connctionMap = new ConcurrentHashMap<String, GpsConnection>();

    @Autowired
    private IOnlineAnalyzeService onlineAnalyzeService;

    @Autowired
    private IRealDataService realDataService;

    @Autowired
    private IOnlineRecordService onlineRecordService;

    /**
     * 开辟线程，同步更新GPS连接信息到redis缓存或数据库
     */
    private Thread checkConnectionStateThread;

    /**
     * 同步时间间隔，默认是30s
     */
    private int checkConnectionInterval = 30 * 1000;


    public Collection<GpsConnection> getConnections() {
        return connctionMap.values();
    }

    @Value("#{config.maxOfflineTime}")
    private int maxOfflineTime;

    @Value("#{config.minOfflineTime}")
    private int minOfflineTime;

    /**
     * spring加载类的时候，自动启动
     */
    public void start() {
        startUpdate = true;
        checkConnectionStateThread = new Thread(new Runnable() {
            public void run() {
                updateConnectionInfoThreadFunc();
            }
        });
        checkConnectionStateThread.start();

    }
    public void stop()
    {
        try
        {
            startUpdate = false;
            checkConnectionStateThread.join(30000);
        }catch (Exception ex)
        {
            logger.error(ex.getMessage(),ex);
        }
    }

    private void updateConnectionInfoThreadFunc()
    {
        long loopTimes = 0;
        while(startUpdate)
        {
            try {
                Collection<GpsConnection> v = connctionMap.values();
                for (GpsConnection conn : v) {
                    String simNo = conn.getSimNo();
                    Date now = new Date();
                    double sec = DateUtil.getSeconds(conn.getOnlineDate(), now);
                    int offlineTime = conn.isConnected()  ? maxOfflineTime : minOfflineTime;
                    boolean isOnline = sec < offlineTime;
                    //终端超过最大心跳时间，判断为离线
                    boolean isOnlineChanged = isOnline != conn.isVehicleOnline();
                    if (isOnlineChanged) {
                        GPSRealData rd = this.realDataService.get(simNo);
                        if (rd != null) {
                            rd.setOnline(isOnline);
                            rd.setOnlineDate(conn.getOnlineDate());
                            conn.setVehicleOnline(isOnline);
                            conn.setPlateNo(rd.getPlateNo());
                            this.realDataService.update(rd);
                            onlineAnalyzeService.checkOnline(rd);
                        }
                    }else
                    {
                        if(loopTimes % 60 == 0 )
                        {
                            GPSRealData rd = this.realDataService.get(simNo);
                            if(rd != null)
                            {
                                if(conn.isConnected()) {
                                    if (rd.getOnlineDate().compareTo(conn.getOnlineDate()) < 0) {
                                        rd.setOnlineDate(conn.getOnlineDate());
                                    }
                                    conn.setPlateNo(rd.getPlateNo());
                                }

                                if(conn.isVehicleOnline() == false && rd.getOnline())
                                {
                                    rd.setOnline(false);
                                    rd.setOnlineDate(conn.getOnlineDate());
                                }
                            }
                        }

                    }

                }
            }catch (Exception ex)
            {
                logger.error(ex.getMessage(),ex);
            }

            loopTimes++;
            if(loopTimes > Integer.MAX_VALUE)
                loopTimes = 0;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
            }
        }
    }

    @Override
    public GpsConnection getConnection(long sessionId, T808Message msg) {
        if (msg == null || msg.getSimNo() == null) {
            logger.error("收到空消息");
            return null;
        }
        GpsConnection conn = connctionMap.get(msg.getSimNo());
        if (conn == null) {
            conn = new GpsConnection(msg.getSimNo(), sessionId);
            connctionMap.put(msg.getSimNo(), conn);
        } else if (conn.getSessionId() != sessionId) {
            conn.setSessionId(sessionId);
        }
        Date now = new Date();
        //终端上线
        /**
        if(conn.isOnline() == false || conn.getPlateNo() == null)
        {
            GPSRealData rd = this.realDataService.get(msg.getSimNo());
            if(rd != null)
            {
                rd.setOnline(true);
                rd.setOnlineDate(now);
                conn.setPlateNo(rd.getPlateNo());
                this.realDataService.update(rd);
                onlineAnalyzeService.checkOnline(rd);
            }
        }*/

        conn.setOnline(true);
        conn.setOnlineDate(now);
        conn.setSessionId(sessionId);
        conn.setConnected(true);
        return conn;
    }

    @Override
    public GpsConnection getConnection(String simNo) {
        if (simNo.length() > 11)
            simNo = simNo.substring(1);
        GpsConnection conn = connctionMap.get(simNo);
        return conn;
    }

    /**
     * 关闭连接
     * @param simNo
     */
    @Override
    public void closeConnection(String simNo)
    {
        GpsConnection conn = getConnection(simNo);
        if (conn != null) {
            // connctionMap.remove(simNo);
            conn.setConnected(false);
            conn.setOnlineDate(new Date());
            conn.setDisconnectTimes(conn.getDisconnectTimes() + 1);
        }
    }

    @Override
    public Collection<GpsConnection> getAllConnections() {
        return connctionMap.values();
    }
}
